package com.stxx.assistant.framwork.utils;

import cn.hutool.core.util.StrUtil;
import com.stxx.assistant.framwork.exception.ServiceException;
import com.stxx.assistant.framwork.utils.dbmeta.DbMeta;
import lombok.Cleanup;
import lombok.Data;
import org.noear.snack.ONode;
import org.noear.solon.Solon;
import org.noear.solon.data.sql.SqlUtilsFactory;
import java.sql.*;
import java.util.*;

/**
 * @author Fuzhenlei
 * @date 2025/01/13 17:17
 */
public class DbMetaUtils {
    private static SqlUtilsFactory factory;
    private static Map<String,DbMeta> metaMap = new HashMap<>();
    private static <T> List<T> sql(DatasourceConfig config,String sql,Class<T> clazz){
        try {
            Class.forName(config.getDriver());
            @Cleanup Connection conn = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
            @Cleanup Statement stmt =conn.createStatement();
            @Cleanup ResultSet rs = stmt.executeQuery(sql);
            ResultSetMetaData metaData = rs.getMetaData();
            Map<String, Object> map = new HashMap<>();
            List<T> list = new ArrayList<>();
            while (rs.next()) {
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    String name = metaData.getColumnName(i);
                    Object value = rs.getObject(i);
                    map.put(StrUtil.toCamelCase(name), value);
                }
                list.add(ONode.load(map).toObject(clazz));
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static DbMeta getMeta(String dbType) {
        if(metaMap.isEmpty()){
            List<DbMeta> list = Solon.context().getBeansOfType(DbMeta.class);
            list.forEach(item->{
                metaMap.put(item.getDbName(),item);
            });
        }
        DbMeta meta = metaMap.get(dbType);
        if(meta==null){
            throw new ServiceException("未找到数据库元数据配置");
        }
        return meta;
    }

    public static List<Table> tables(DatasourceConfig config) {

        return  sql(config,
                getMeta(config.getDbType()).getTableSql(config.getSchema()),
                Table.class);
    }
    public static List<Column> columns(DatasourceConfig config,String tableName) {
        return sql(config
                ,getMeta(config.getDbType()).getColumnSql(config.getSchema(),tableName)
                ,Column.class);
    }



    public static interface DatasourceConfig{
        String getDbType();
        String getDriver();
        String getSchema();
        String getUrl();
        String getUsername();
        String getPassword();

    }

    @Data
    public static class Table{
        private String tableName;
        private String tableComment;
        private String pk;
        private List<Column> columns;
    }

    @Data
    public static class Column{
        private String columnName;
        private String columnComment;
        private String dataType;
        private Short len;
        private Short decimals;
        private Boolean isPk;
    }
}
